import re
from QQLoginTool.QQtool import OAuthQQ
from django import http
from django.contrib.auth import login
from django_redis import get_redis_connection

from apps.carts.utils import merge_cart_cookie_to_redis
from apps.users.models import User
from django.shortcuts import redirect, render
from django.urls import reverse
from django.views import View

from apps.oauth.models import OAuthQQUser
from apps.oauth.utils import check_access_token, generate_access_token
from meiduo_mall import settings
import logging

logger = logging.getLogger('django')


# 拼接url,获取qq登陆扫码页面
class QQAuthURLView(View):
    def get(self, request):
        oauth_qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                           client_secret=settings.QQ_CLIENT_SECRET,
                           redirect_uri=settings.QQ_REDIRECT_URI,
                           state='test')

        login_url = oauth_qq.get_qq_url()
        return http.JsonResponse({'login_url': login_url})


# 使用Authorization_Code获取Access_Token,使用Access_Token向qq服务器请求openid
class QQAuthUserView(View):
    def get(self, request):
        code = request.GET.get('code')
        if not code:
            return http.HttpResponseBadRequest('缺少code')

        oauth_qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                           client_secret=settings.QQ_CLIENT_SECRET,
                           redirect_uri=settings.QQ_REDIRECT_URI,
                           state='test')
        try:
            # 获取token
            access_token = oauth_qq.get_access_token(code)
            # 请求openid
            openid = oauth_qq.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            return http.HttpResponseBadRequest('OAuth认证失败')
        # 是否绑定手机号
        try:
            oauth_qq = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 对openid进行加密
            token = generate_access_token(openid)
            # 未绑定手机号:返回到绑定页
            return render(request, 'oauth_callback.html', context={'openid': token})
        else:
            # 已绑定手机号:设置session
            login(request, oauth_qq.user)
            response = redirect(reverse('contents:index'))
            response.set_cookie('username', oauth_qq.user.username, max_age=15 * 24 * 60 * 60)
            return response

    def post(self, request):
        # 接收数据
        mobile = request.POST.get('mobile')
        password = request.POST.get('pwd')
        sms_code = request.POST.get('sms_code')
        openid = request.POST.get('openid')
        # 检验数据
        # 参数是否齐全
        if not all([mobile, password, sms_code]):
            return http.HttpResponseBadRequest('缺失参数')
        # 手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('请输入正确的手机号码')
        # 密码是否符合要求
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', password):
            return http.HttpResponseBadRequest('请输入正确格式的密码')
        # 短信验证码一致
        redis_conn = get_redis_connection('code')
        sms_code_server = redis_conn.get('sms:%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '验证码无效'})
        if sms_code_server != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '验证码错误'})
        # 对openid进行解密
        openid = check_access_token(openid)
        if not openid:
            return render(request, 'oauth_callback.html', {'openid_errmsg': '无效的openid'})
        # 保存注册数据
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            user = User.objects.create_user(username=mobile,
                                            password=password,
                                            mobile=mobile)
        else:
            if not user.check_password(password):
                return http.HttpResponseBadRequest('信息错误,绑定失败')
        # 用户绑定openid
        try:
            OAuthQQUser.objects.create(openid=openid, user=user)
        except Exception as e:
            return http.HttpResponseBadRequest('QQ登陆失败')
        # 登陆
        login(request, user)

        # 跳转
        response = redirect(reverse('contents:index'))
        response.set_cookie('username', user.username, max_age=14 * 24 * 60 * 60)
        # 同步购物车
        merge_cart_cookie_to_redis(request,user,response)
        return response
